package top.pengdev.esoffice.util;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import static org.elasticsearch.client.RequestOptions.DEFAULT;

/**
 * @author pengdev
 * @description
 * @date 2020-11-25 20:27
 **/
@Component
public class EsUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(EsUtils.class);
    @Resource
    private RestHighLevelClient client;

    /**********************************操作索引****************************************/

    /**
     * 创建elasticsearch索引
     * @param index 索引名
     * @return
     */
    public boolean create(String index){
        if (exists(index)){
            return true;
        }

        CreateIndexRequest request = new CreateIndexRequest(index);
        try{
            CreateIndexResponse response = client.indices().create(request, DEFAULT);
            return response.isAcknowledged();
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 判断elasticsearch是否存在
     * @param index 索引名
     * @return
     */
    public boolean exists(String index){
        GetIndexRequest request = new GetIndexRequest();
        try {
            request.indices(index);
            return client.indices().exists(request, DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 删除一个elasticsearch索引
     * @param index 索引名
     * @return
     */
    public boolean delete(String index){
        if (! exists(index)){
            return false;
        }
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        try {
            DeleteIndexResponse response = client.indices().delete(request, DEFAULT);
            return response.isAcknowledged();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**********************************操作文档****************************************/
    private static final String DOC = "_doc";
    private static final int DEFAULT_TIMEOUT = 1;
    private int timeout;

    /**
     * 在elasticsearch索引下 创建文档
     * @param index 索引名
     * @param json 文档信息
     * @param id 文档id
     * @return
     */
    public boolean create(String index, String json, String id){
        IndexRequest request = new IndexRequest(index);
        request.timeout(TimeValue.timeValueSeconds(getTimeout()));
        request.source(json, XContentType.JSON);
        if (StringUtils.hasLength(id)){
            request.id(id);
        }
        try {
            IndexResponse response = client.index(request, DEFAULT);
            return RestStatus.CREATED.equals(response.status());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 在elasticsearch索引下 创建文档
     * @param index 索引名
     * @param json 文档信息
     * @return
     */
    public boolean create(String index, String json){
        return create(index, json, null);
    }

    /**
     * 在elasticsearch索引下 批量创建文档
     * @param index 索引名
     * @param jsons id-json 格式的多个json数据
     * @return
     */
    public boolean batchCreate(String index, Map<String, String> jsons){
        BulkRequest request = new BulkRequest();
        for (Map.Entry<String, String> entry : jsons.entrySet()) {
            request.add(new IndexRequest(index)
                    .id(entry.getKey())
                    .source(entry.getValue(), XContentType.JSON));
        }
        try {
            BulkResponse response = client.bulk(request, DEFAULT);
            return !response.hasFailures();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 判断elasticsearch索引下，文档id是否存在
     * @param index
     * @param id
     * @return
     */
    public boolean exists(String index, String id){
        GetRequest request = new GetRequest(index);
        request.id(id);
        //不获取source，增加效率
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none_");
        try {
            return client.exists(request, DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取elasticsearch索引下， 文档id的内容
     * @param index
     * @param id
     * @return
     */
    public String getAsString(String index, String id){
        GetResponse response = getResponse(index, id);
        if (null != response){
            return response.getSourceAsString();
        }
        return "";
    }

    /**
     * 获取elasticsearch索引下， 文档id的内容
     * @param index
     * @param id
     * @return
     */
    public Map<String, Object> getAsMap(String index, String id){
        GetResponse response = getResponse(index, id);
        if (null != response){
            return response.getSourceAsMap();
        }
        return Collections.emptyMap();
    }

    /**
     * 更新文档
     * @param index 索引名
     * @param json json数据
     * @param id 文档id
     * @return
     */
    public boolean update(String index, String json, String id){
        UpdateRequest request = new UpdateRequest();
        request.id(id);
        request.timeout(TimeValue.timeValueSeconds(getTimeout()));
        request.doc(json, XContentType.JSON);
        try {
            UpdateResponse response = client.update(request, DEFAULT);
            return RestStatus.OK.equals(response.status());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean delete(String index, String id){
        DeleteRequest request = new DeleteRequest(index);
        request.id(id);
        try {
            DeleteResponse response = client.delete(request, DEFAULT);
            return RestStatus.OK.equals(response.status());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public void search(String index, Map<String, String> exactQuery){
        SearchRequest request = new SearchRequest(index);

        //构建搜索条件
        SearchSourceBuilder builder = new SearchSourceBuilder();

        for (Map.Entry<String, String> entry : exactQuery.entrySet()) {
            QueryBuilders.termQuery("name", "");

        }


    }

    private GetResponse getResponse(String index, String id){
        GetRequest request = new GetRequest(index);
        request.id(id);
        try {
            GetResponse response = client.get(request, DEFAULT);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public int getTimeout() {
        return timeout < 0 ? DEFAULT_TIMEOUT : timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
}
